#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import sys
import dbus
import signal
import shutil
import pathlib
import logging
import asyncio
import strict_hwcfg
from gi.repository import GLib
from pdc_util import PdcUtil
from pdc_util import StdoutRedirector
from pdc_param import PdcConst
from pdc_plugin_manager import PdcPluginManager



class PdcDaemon:

    def __init__(self, param):
        self.param = param
        self._bFinallizing = False

    def run(self):
        self._loadMainCfg()
        try:
            # create directories
            PdcUtil.preparePersistDir(PdcConst.cacheDir, 0, 0, 0o755)
            PdcUtil.preparePersistDir(PdcConst.logDir, 0, 0, 0o755)
            PdcUtil.prepareTransientDir(PdcConst.runDir, 0, 0, 0o755)

            try:
                # initialize logging
                sys.stdout = StdoutRedirector(os.path.join(PdcConst.logDir, "peripheral-data-collector.out"))
                sys.stderr = sys.stdout

                # initialize logging
                logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
                logging.getLogger().setLevel(self.param.logLevel)
                logging.info("Program begins.")

                # write pid file
                pathlib.Path(PdcConst.pidFile).write_text(str(os.getpid()))

                # create machine
                self.param.machine = strict_hwcfg.probe()

                # create mainloop
                dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
                self.param.mainloop = asyncio.get_event_loop()

                # create plugin manager
                self.param.pluginManager = PdcPluginManager(self.param)
                self.param.pluginManager.start()

                # start main loop
                logging.info("Mainloop begins.")
                GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, self._sigHandlerINT, None)
                GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, self._sigHandlerTERM, None)
                self.param.mainloop.run_forever()
                logging.info("Mainloop exits.")
            finally:
                if self.param.pluginManager is not None:
                    self.param.pluginManager.stop()
                self._bFinallizing = True
                logging.shutdown()
        finally:
            shutil.rmtree(PdcConst.runDir)

    def _loadMainCfg(self):
        pass

    def _sigHandlerINT(self, signum):
        if not self._bFinallizing:
            logging.info("SIGINT received.")
            self.param.mainloop.call_soon_threadsafe(self.param.mainloop.stop)
        else:
            logging.info("SIGINT received during finalizing.")
        return True

    def _sigHandlerTERM(self, signum):
        if not self._bFinallizing:
            logging.info("SIGTERM received.")
            self.param.mainloop.call_soon_threadsafe(self.param.mainloop.stop)
        else:
            logging.info("SIGTERM received during finalizing.")
        return True
